package com.yc.dao.impl;

import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.persistence.MappedSuperclass;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Order;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.yc.dao.BaseDaoHib;

@SuppressWarnings("unchecked")
@MappedSuperclass
public abstract class BaseDaoHibImpl <M extends java.io.Serializable , PK extends java.io.Serializable> implements BaseDaoHib<M, PK> {

	protected static final Logger LOGGER=LoggerFactory.getLogger(BaseDaoHibImpl.class);
	
	private Class<M> entityClass;//取出Person类的反射实例	from：类名
	private String HQL_LIST_ALL;//查询所有的hql语句
	private String HQL_COUNT_ALL;//计算数目
	
	public BaseDaoHibImpl(){
		this.entityClass=(Class<M>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		HQL_LIST_ALL="from "+this.entityClass.getSimpleName();
		HQL_COUNT_ALL=" select count(*) from "+this.entityClass.getSimpleName();
	}
	
	@Resource(name="sessionFactory")
	private SessionFactory sessionFactory;
	
	public Session getSession(){
		//事务必须是开启的（Required），否则获取不到
		return sessionFactory.getCurrentSession();
	}
	
	public PK save(M model){
		return (PK) getSession().save(model);
	}
	
	public void saveOrUpdate(M model){
		getSession().saveOrUpdate(model);
	}
	
	public void update(M model){
		getSession().update(model);
	}
	
	public List<M> findByExample(M model){
		List<M> results=getSession().createCriteria(this.entityClass).add(Example.create(model)).list();
		return results;
	}
	
	public List<M> findByCriterion(Criterion criterion,Order order,Integer offset,Integer length){
		Criteria criteria=getSession().createCriteria(this.entityClass);
		criteria.add(criterion);
		
		if(order!=null){
			criteria.addOrder(order);
		}
		if(offset!=null){
			criteria.setFirstResult(offset);
		}
		if(length!=null){
			criteria.setMaxResults(length);
		}
		return criteria.list();
	}
	
	public List<M> findByProperty(Map<String, Object> param,int offset,int length){
		StringBuffer querString=new StringBuffer("from "+this.entityClass.getSimpleName()+" where ");
		List<Object> values=new ArrayList<Object>();
		boolean firstParam = true;
		for(Map.Entry<String, Object> entry:param.entrySet()){
			values.add(entry.getValue());
			if(!firstParam){
				querString.append(" and ");
			}
			querString.append(entry.getKey()+"= ? ");
			firstParam=false;
		}
		Query queryObject=getSession().createQuery(querString.toString());
		for(int i=0;i<values.size();i++){
			queryObject.setParameter(0,values.get(i));
		}
		return queryObject.list();
	}
	
	public void merge(M model){
		getSession().merge(model);
	}
	
	public void delete(PK id){
		getSession().delete(id);
	}
	
	public boolean exists(PK id){
		return get(id) !=null;
	}
	
	public M get(PK id){
		return (M) getSession().get(this.entityClass, id);
	}
	
	public List<M> getAll(){
		return getSession().createQuery(HQL_LIST_ALL).list();
	}
	
	public long countAll(){
		return (Long) getSession().createQuery(HQL_COUNT_ALL).uniqueResult();
	}

}
